package com.hb.trade.server.project.util;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.hb.core.pojo.enums.InvoiceTypeEnum;
import com.hb.core.pojo.project.order.dto.InvoicePdfDTO;
import com.hb.core.pojo.project.order.dto.InvoicingResultDTO;
import com.hb.core.pojo.project.order.entity.Invoice;
import com.hb.trade.server.project.config.InvoiceConfig;
import lombok.extern.slf4j.Slf4j;
import org.fzzn.core.model.enums.LogicEnum;
import org.fzzn.core.util.Enums;
import org.fzzn.core.util.IdUtil;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * describe:
 * 发票的util
 * @author zhongdl
 * @date 2022/04/15
 */
@Slf4j
public class InvoiceUtil {

    /**
     * @param invoiceType: 发票类型：专票004、普票007、电子普票026、普票（卷式）025、电子专票028
     * @param invoiceAmount:发票金额
     * @param purchaserName: 购方单位名称
     * @param purchaserIdentification:购方单位识别号
     * @param purchaserAddress: 购方地址
     * @param purchaserPhone: 购方电话
     * @param purchaserBankAccount:购方银行账号
     * @param orderNo:订单号
     * @Description:开具发票
     * @Author: zhongdl
     * @Date:2022/4/15 13:56

     * @return: {@link com.hb.core.pojo.project.order.dto.InvoicingResultDTO }
     **/
    public static InvoicingResultDTO  invoice(String invoiceType,
                                              String invoiceAmount,
                                              String purchaserName,
                                              String purchaserIdentification,
                                              String purchaserAddress,
                                              String purchaserPhone,
                                              String purchaserBankAccount,
                                              String orderNo
                                              ){
        InvoicingResultDTO invoicingResultDTO = new InvoicingResultDTO();
        Long id = IdUtil.getId();

        // 设置请求参数
        JSONObject jsonObject = JSONUtil.createObj();
        // 机器编号
        jsonObject.putOpt("kpzdbs", InvoiceConfig.fiscalProcessorCode);
        // 发票类型代码
        jsonObject.putOpt("fplxdm", InvoiceTypeEnum.ORDINARY_ELECTRONIC_INVOICE.getDicLabel());
        // 发票请求流水号
        jsonObject.putOpt("fpqqlsh", String.valueOf(id));
        // 开票类型 0：正数票开具 1：负数票开具
        jsonObject.putOpt("kplx", "0");
        //特殊票种标识 “00”不是 “01”农产品销售 “02”农产品收购 “06”抵扣通行费 “07”其它通行费 “08”成品油销售
        jsonObject.putOpt("tspz", "00");
        // 销货单位识别号
        jsonObject.putOpt("xhdwsbh", InvoiceConfig.sellerIdentification);
        // 销货单位名称
        jsonObject.putOpt("xhdwmc", InvoiceConfig.sellerName);
        // 销货单位地址电话
        jsonObject.putOpt("xhdwdzdh", InvoiceConfig.sellerName + InvoiceConfig.sellerPhone);
        // 销货单位银行账号
        jsonObject.putOpt("xhdwyhzh", InvoiceConfig.sellerBankAccount);
        // 购货单位识别号invoiceSubmitInfoDTO
        jsonObject.putOpt("ghdwsbh", purchaserIdentification);
        // 购货单位名称
        jsonObject.putOpt("ghdwmc", purchaserName);
        // 购货单位地址电话
        jsonObject.putOpt("ghdwdzdh", (StrUtil.isEmpty(purchaserAddress) ? "" : purchaserAddress) + (StrUtil.isEmpty(purchaserPhone) ? "" : purchaserPhone));
        // 购货单位银行账号
        jsonObject.putOpt("ghdwyhzh", purchaserBankAccount);
        // 清单标志 0：无清单; 1：带清单 Ukey开具清单负数是清单标志传0
        jsonObject.putOpt("qdbz", "0");
        // 征税方式 0：普通征税 1：减按计征 2：差额征税（附件3）
        jsonObject.putOpt("zsfs", "0");
        // 费用项目数量
        jsonObject.putOpt("fyxm", "<fyxm count=\"0\">");
        //单条金额
        BigDecimal jeInvoiceAmount = new BigDecimal(invoiceAmount);
        ArrayList<Map<String, String>> group = new ArrayList<>();
        Map<String, String> map = new HashMap<String, String>();
        map.put("xh", "1");
        map.put("fphxz", "0");
        map.put("spmc", "系统使用费");
        map.put("je", invoiceAmount);
        map.put("sl", "0");
        // 税率
        BigDecimal invoiceTaxRate = new BigDecimal(InvoiceTypeEnum.getInvoiceTaxRate(invoiceType));
        // 合计金额 普票金额=含税收入/（1+0%）；专票金额=含税收入/（1+3%）
        BigDecimal jeAmount = jeInvoiceAmount.divide(invoiceTaxRate, 2, RoundingMode.HALF_UP);
        String jeAmountStr = jeAmount.setScale(2, RoundingMode.HALF_UP).toString();
        // 合计税额 普票税额=0，专票税额=含税收入/（1+3%）*3%=含税收入-合计金额
        BigDecimal seTotalTax = jeInvoiceAmount.subtract(new BigDecimal(jeAmountStr));
        String seStr = seTotalTax.setScale(2, RoundingMode.HALF_UP).toString();

        map.put("se", seStr);
        map.put("hsbz", "1");
        map.put("spbm", InvoiceConfig.spbm);
        group.add(map);
        jsonObject.putOpt("group", group.toArray());

        // 价税合计
        BigDecimal totalPrice = new BigDecimal(invoiceAmount);
        String totalPriceStr = totalPrice.setScale(2, RoundingMode.HALF_UP).toString();
        // 合计金额 普票金额=含税收入/（1+0%）；专票金额=含税收入/（1+3%）
        BigDecimal totalAmount = totalPrice.divide(invoiceTaxRate, 2, RoundingMode.HALF_UP);
        String totalAmountStr = totalAmount.setScale(2, RoundingMode.HALF_UP).toString();
        // 合计税额 普票税额=0，专票税额=含税收入/（1+3%）*3%=含税收入-合计金额
        BigDecimal totalTax = totalPrice.subtract(new BigDecimal(totalAmountStr));
        String totalTaxStr = totalTax.setScale(2, RoundingMode.HALF_UP).toString();

        // 合计金额
        jsonObject.putOpt("hjje", totalAmountStr);
        // 合计税额
        jsonObject.putOpt("hjse", totalTaxStr);
        // 价税合计
        jsonObject.putOpt("jshj", totalPriceStr);
        // 开票人
        jsonObject.putOpt("kpr", "于林卉");
        //备注
        if (StrUtil.isNotEmpty(orderNo)){
            jsonObject.putOpt("bz", "订单号:"+orderNo);
        }
        //测试环境先写死数据
        if (Enums.equals(LogicEnum.YES,InvoiceConfig.ceShiFlag)){
            //发票代码
            invoicingResultDTO.setInvoiceCode("037002100211");
            //发票号码
            invoicingResultDTO.setInvoiceNumber("31865871");
            //开票日期
            invoicingResultDTO.setInvoiceTime("20220518095748");
            //税控码
            invoicingResultDTO.setControlledTaxCode("00341>+*-/01><*-5+611-593+/91*>+*13*6-8>86**//112+2137-049>4*195*01>0->82>2*2+*620041/-1279888-0*201>>/719527*/5");
            //校验码
            invoicingResultDTO.setCheckCode("06074093804070876403");
            //二维码
            invoicingResultDTO.setQrCode("iVBORw0KGgoAAAANSUhEUgAAAJQAAACUCAIAAAD6XpeDAAADCElEQVR42u3aW3LCMAwF0O5/03QFTLGlKzvl8MkwSaxjJnr45yfweRU+766TuNcnz/DJ81Sued0HHjx48L4ELxH0BExlXZW1V66ZiDM8ePDgwevBqwQlcZ2bN9PqNbviAw8ePHjw7sW7bfGTDQR48ODBgwevWqSnn2FyU8KDBw8evDN46Zf5DbPJREO80jS4bqoADx48eP8YLxE435/dxPDg+R4evJ6XZ1dSkBicJgat6WRk+b7w4MGDB287tl0v2EnsRCM7PYztiic8ePDgwVtbVyLR6FpkJUFIBDrxnKXfw4MHDx68jnlkqQE9mWik75VOZCobAh48ePDg9RTmleZvOnkZ3aGDSc1y/OHBgwcPXktfNFEkTqKeGromhsbLMYcHDx48eH/WeekGcVcQ00E/1Zhe3sTw4MGDB2+7/usqcrsGtunEIT1Y7kruSt0WePDgwYO3Hbiu4WR6kekEZ3LDvf09PHjw4MFr6S0nBobpAD1lsJxOGOHBgwcPXn9RmUhkJpvdk4eLIgkgPHjw4MHbxku8kBNFaNsA89DBpMgBJHjw4MGDt1T/vcKfm4e66aQpfaALHjx48OD14N1wSOlUQ/y254QHDx48eNkiPTEgTdwrkewksNueHx48ePDgbeNNFt2JTTC5IRJxWF47PHjw4MHbXvtTmraTB5lONZ3hwYMHD97c+zXdgE40xBON5sdMFeDBgwcPXovFDc3oBHxig3YNfuP/Qnjw4MH7crzJJCX98k/ca3Jd8Q4LPHjw4MHbfuGPZlCDA9KuAW+6mQ4PHjx48PbxEoPQycK5ApbecJGkDB48ePDgtS+gsuDEwLYS9PSwtKtx//Z7ePDgwYN3PCe4oWDvKq67fhMv0uHBgwcPXktv8ymN5vQhqK7ngQcPHjx4d+Gli9Z0IZxIuE410D+6Lzx48ODBuxYvPcxMJCOJYfUjExZ48ODBg3e8uXwDTKI5Xstk4MGDBw/eVGP6VMHeNVxNDF0jB6XgwYMHD97xA0iT79rJ4j0R9FPNbnjw4MH7Erxf3JoY08YiFCkAAAAASUVORK5CYII=");
            invoicingResultDTO.setCode("0");
            invoicingResultDTO.setMessage("测试环境");
            return invoicingResultDTO;
        }
        String result = HttpRequest.post(InvoiceConfig.invoicingUrl())
                // 设置请求头
                // a5ad6358-74bd-1756-4d73-8f7b3dc006e8
                .header("accountToken", "11111")
                // 传递参数
                .body(jsonObject.toString())
                .execute()
                .body();
        System.out.println(result);
        JSONObject resultJson = JSONUtil.parseObj(result);
        //状态码0为成功
        String code = resultJson.get("code", String.class);
        String message = resultJson.get("message", String.class);
        invoicingResultDTO.setCode(code);
        invoicingResultDTO.setMessage("测试环境假数据");
        //如果没成功直接返回
        if (!String.valueOf(0).equals(code)){
            log.info("发票开具失败{}",message);
            return invoicingResultDTO;
        }
        JSONObject data = JSONUtil.parseObj(resultJson.get("data"));
        //发票代码
        invoicingResultDTO.setInvoiceCode(data.get("fpdm",String.class));
        //发票号码
        invoicingResultDTO.setInvoiceNumber(data.get("fphm",String.class));
        //开票日期
        invoicingResultDTO.setInvoiceTime(data.get("kprq",String.class));
        //税控码
        invoicingResultDTO.setControlledTaxCode(data.get("skm",String.class));
        //校验码
        invoicingResultDTO.setCheckCode(data.get("jym",String.class));
        //二维码
        invoicingResultDTO.setQrCode(data.get("ewm",String.class));

        log.info("发票开具成功{}",invoicingResultDTO);

        return invoicingResultDTO;
    }
    /**
     * @param invoiceTime: 开票时间
     * @param invoiceCode: 发票代码
     * @param invoiceNumber:发票号码
     * @Description:获得开票的pdf
     * @Author: zhongdl
     * @Date:2022/4/15 14:10

     * @return: {@link com.hb.core.pojo.project.order.dto.InvoicePdfDTO }
     **/
    public static InvoicePdfDTO invoicePdf(String invoiceTime,String invoiceCode,String invoiceNumber){
        InvoicePdfDTO invoicePdfDTO = new InvoicePdfDTO();
        JSONObject jsonObject = JSONUtil.createObj();
        //应用类型代码
        //1：国税应用 2：地税应用
        jsonObject.putOpt("yylxdm","1");
        //销售方的税号
        jsonObject.putOpt("nsrsbh",InvoiceConfig.sellerIdentification);
        //开标日期
        jsonObject.putOpt("kprq",invoiceTime);
        //发票代码
        jsonObject.putOpt("fpdm",invoiceCode);
        //发票号码
        jsonObject.putOpt("fphm",invoiceNumber);
        String result = HttpRequest.post(InvoiceConfig.invoicePdfUrl())
                // 设置请求头
                // a5ad6358-74bd-1756-4d73-8f7b3dc006e8
                .header("accountToken", "11111")
                // 传递参数
                .body(jsonObject.toString())
                .execute()
                .body();
        //如果没成功直接返回
        JSONObject resultJson = JSONUtil.parseObj(result);
        //状态码0为成功
        String code = resultJson.get("code", String.class);
        String message = resultJson.get("message", String.class);
        invoicePdfDTO.setCode(code);
        invoicePdfDTO.setMessage(message);
        if (!String.valueOf(0).equals(code)){
            return invoicePdfDTO;
        }
        JSONObject data = JSONUtil.parseObj(resultJson.get("data"));
        //pdfUrl
        invoicePdfDTO.setPdfUrl(data.get("pdfUrl",String.class));
        //Base64加密的code
        invoicePdfDTO.setPdfCode(data.get("pdfcode",String.class));
        System.out.println(result);
        return invoicePdfDTO;
    }

    /**
     *
     * @Description:注销发票
     * TODO注销发票不可用(只能验签失败的可以调用)

     **/
    public static void voidInvoice(JSONArray jsonArray){

        for (Object jsonValue : jsonArray) {
            JSONObject jsonObject = JSONUtil.parseObj(jsonValue);
            JSONObject paramJson = JSONUtil.createObj();
            paramJson.putOpt("kpzdbs","127006794971");
            paramJson.putOpt("fplxdm","026");
            paramJson.putOpt("zflx","1");
            paramJson.putOpt("fpdm",jsonObject.get("fpdm"));
            paramJson.putOpt("fphm",jsonObject.get("fphm"));
            paramJson.putOpt("hjje",jsonObject.get("hjje"));
            paramJson.putOpt("zfr",jsonObject.get("kpr"));
            if (!"于林卉".equals(jsonObject.get("kpr"))){
                continue;
            }
            String result = HttpRequest.post("http://101.200.158.179:30717/invoice/voidInvoice")
                    // 设置请求头
                    // a5ad6358-74bd-1756-4d73-8f7b3dc006e8
                    .header("accountToken", "11111")
                    // 传递参数
                    .body(paramJson.toString())
                    .execute()
                    .body();
            System.out.println(result);
        }
    }

    /**
     *
     * @Description:查询发票的逻辑
     * TODO

     **/
    public static JSONArray invoiceSearch(){
        JSONObject jsonObject = JSONUtil.createObj();

        jsonObject.putOpt("kpzdbs","127006794971");
        jsonObject.putOpt("fplxdm","026");
        jsonObject.putOpt("cxfs","1");
        jsonObject.putOpt("cxtj","2022041520220415");
        String result = HttpRequest.post("http://101.200.158.179:30717/invoice/invoiceSearch")
                // 设置请求头
                // a5ad6358-74bd-1756-4d73-8f7b3dc006e8
                .header("accountToken", "11111")
                // 传递参数
                .body(jsonObject.toString())
                .execute()
                .body();
        JSONObject jsonObject1 = JSONUtil.parseObj(result);
        Object data = jsonObject1.get("data");
        Object group = JSONUtil.parseObj(data).get("group");
        return JSONUtil.parseArray(group);
    }

}
